package com.fablesoft.projectdatacollect.http;

import java.io.BufferedInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import com.fablesoft.projectdatacollect.MyApplication;
import com.fablesoft.projectdatacollect.bean.BaseResponse;
import com.fablesoft.projectdatacollect.util.Config;
import com.fablesoft.projectdatacollect.util.Log4jUtil;
import com.fablesoft.projectdatacollect.util.LogUtil;

import android.text.TextUtils;
import android.util.Log;

/**
 */
public final class HttpUploadThread extends Thread {
	/**
	 * 日志标签
	 */
	private static final String TAG = "HttpThread";

	/**
	 * 用户控制是否中断请求的标志
	 */
	private boolean cancel = false;

	/**
	 * 请求url
	 */
	private String url;

	/**
	 * POST请求数据
	 * 
	 */
	private Map<String, Object> parms;

	/**
	 * POST请求数据
	 * 
	 */
	private List<File> files;
	
	private byte[] file;

	/**
	 * HTTP请求监听的实现类，当请求有结果时会设置该类的相应方法
	 */
	private HttpListener listener;

	private Class clazz;
	
	private PrepareUpload prepareUpload;
	
	/**
	 * 构造方法
	 * 
	 * @param url
	 *            请求url
	 * @param listener
	 *            实现监听请求状态的类
	 *
	 */
	public HttpUploadThread(String url, HttpListener listener, List<File> files,
			Map<String, Object> parms, Class clazz) {
		this.url = url;
		LogUtil.i(TAG, "url:" + url);
		this.parms = parms;
		this.listener = listener;
		this.files = files;
		this.clazz = clazz;
	}

	public HttpUploadThread(String url, HttpListener listener, Map<String, Object> parms, 
			Class clazz, PrepareUpload prepareUpload) {
		this.url = url;
		LogUtil.i(TAG, "url:" + url);
		this.parms = parms;
		this.listener = listener;
		this.clazz = clazz;
		this.prepareUpload = prepareUpload;
	}
	
	public HttpUploadThread(String url, HttpListener listener, byte[] file,
			Map<String, Object> parms, Class clazz) {
		this.url = url;
		LogUtil.i(TAG, "url:" + url);
		this.parms = parms;
		this.listener = listener;
		this.file = file;
		this.clazz = clazz;
	}
	
	public interface PrepareUpload{
		List<File> doBeforeUpload();
	}
	
	/**
	 * 发送HTTP请求，并将结果设置回HttpListener的实现类中
	 * 
	 */
	@Override
	public void run() {
		if(prepareUpload != null){
			this.files = prepareUpload.doBeforeUpload();
		}
		String result = null;
		result = sendRequest();

		// 如果用户还没有中断请求
		if (!cancel) {
			try {
				BaseResponse response = JsonUtil.getResponse(result, clazz);
				if(response != null && "403".equals(response.getCode())){
					listener.onNotLogin(response);
				}else{
					listener.onRequestFinish(response);
				}
			} catch (Exception e) {
				Log4jUtil.e(e.toString());
				e.printStackTrace();
			}
		}
	}

	/**
	 * 发送请求获取响应
	 * 
	 * @return
	 * @see [类、类#方法、类#成员]
	 */
	private String sendRequest() {
		URL myURL = null;
		HttpURLConnection conn = null;
		InputStream is = null;
//		FileInputStream fis = null;
		BufferedInputStream in = null;
		DataOutputStream dos = null;
		StringBuffer response = new StringBuffer();
		String prefix = "--";
		String boundary = "*****";
		String end = "\r\n";
		try {
			Log.d("sglei-upload", "upload url = " + url);
			myURL = new URL(url);
			conn = (HttpURLConnection) myURL.openConnection();
			/* 允许Input、Output，不使用Cache */
			conn.setDoInput(true);
			conn.setChunkedStreamingMode(4096);
			conn.setDoOutput(true);
			conn.setUseCaches(false);
			/* 设置传送的method=POST */
			conn.setRequestMethod("POST");
			/* setRequestProperty */
			conn.setRequestProperty("Connection", "Keep-Alive");
			conn.setRequestProperty("Charset", "UTF-8");
            conn.setRequestProperty("content", "text/html;charset=utf-8");
			conn.setRequestProperty("Content-Type",
					"multipart/form-data;boundary=" + boundary);
            conn.setRequestProperty(Config.CLIENT_TYPE_KEY, Config.CLIENT_TYPE_VALUE);
			LogUtil.i("lzx", "cookie:" + MyApplication.getInstance().getSessionId());
			if(!TextUtils.isEmpty(MyApplication.getInstance().getSessionId())){
				conn.setRequestProperty("Cookie", MyApplication.getInstance().getSessionId());
			}
			/* 设置DataOutputStream */
			dos = new DataOutputStream(conn.getOutputStream());
			if(parms != null){
				for(Entry<String, Object> entry : parms.entrySet()){
					if(entry.getValue() != null && !TextUtils.isEmpty(entry.getValue().toString())){
						dos.writeBytes(prefix + boundary  + end);
						dos.writeBytes("Content-Disposition: form-data; name=\"" + entry.getKey() + "\"" + end);
						dos.writeBytes(end);  
			            dos.write(entry.getValue().toString().getBytes("UTF-8"));
			            dos.writeBytes(end);
					}
				}
			}
			if((files == null || files.size() == 0) && file == null){
				Log.e(TAG,"files is null  or size is 0");
				return null;
			}else{
				if(files != null){
					for(int i=0; i<files.size(); i++){
						dos.writeBytes(prefix + boundary + end);
						dos.writeBytes("Content-Disposition: form-data; "
								+ "name=\"file\";filename=\"file" + i + ".jpg\"" + end);
						dos.writeBytes("Content-Type: application/octet-stream" + end);  
						dos.writeBytes(end);
						/* 取得文件的FileInputStream */
						in = new  BufferedInputStream(new FileInputStream(files.get(i))) ; 
//						fis = new FileInputStream(files.get(i));
						/* 设置每次写入1024bytes */
						int bufferSize = 4096;
						byte[] buffer = new byte[bufferSize];
						int length = -1;
						/* 从文件读取数据至缓冲区 */
						while ((length = in.read(buffer)) != -1) {
							/* 将资料写入DataOutputStream中 */
							dos.write(buffer, 0, length);
							Log.i("lzx", "write file");
						}
						dos.writeBytes(end);
						Log.i("lzx", "write end");
						in.close();
						in = null;
					}
				}else if(file != null){
					dos.writeBytes(prefix + boundary + end);
					dos.writeBytes("Content-Disposition: form-data; "
							+ "name=\"file\";filename=\"file.jpg\"" + end);
					dos.writeBytes("Content-Type: application/octet-stream" + end);  
					dos.writeBytes(end);
					dos.write(file, 0, file.length);
					dos.writeBytes(end);
				}
			}
			dos.writeBytes(prefix + boundary + prefix + end);  
			dos.writeBytes(end); 
	        dos.flush();
            Log.d("sglei-upload", "upload response code = " + conn.getResponseCode());
			/* 取得Response内容 */
	        if (conn.getResponseCode() == 200) {
				is = new BufferedInputStream(conn.getInputStream());
				byte[] buf = new byte[2048];
				is = conn.getInputStream();
				for (int n; (n = is.read(buf)) != -1;) {
					response.append(new String(buf, 0, n, "UTF-8"));
				}
                Log.d("sglei-upload", "upload response = " + response.toString());
			} else {
				Log.e(TAG, "ResponseCode:" + conn.getResponseCode());
			}
		} catch (Exception e) {
			Log4jUtil.e(e.toString());
			response = null;
		} finally {
			if(in != null){
				try {
					in.close();
				} catch (IOException e) {
					Log.e(TAG, "close outputStream " + e.toString());
				}
			}
			if (dos != null) {
				try {
					dos.close();
				} catch (IOException e) {
					Log.e(TAG, "close outputStream " + e.toString());
				}
			}
			if (is != null) {
				try {
					is.close();
				} catch (IOException e) {
					Log.e(TAG, "close inputstream " + e.toString());
				}
			}
			if (conn != null) {
				conn.disconnect();
			}
		}
		return response == null ? null : response.toString();
	}

}
